package com.sunwayworld.basemodule.business.pjtask.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleProductBean;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleProductService;
import com.sunwayworld.basemodule.business.pjtask.bean.LimsPjFolderBean;
import com.sunwayworld.basemodule.business.pjtask.bean.LimsPjFolderEquipBean;
import com.sunwayworld.basemodule.business.pjtask.bean.LimsPjTaskBean;
import com.sunwayworld.basemodule.business.pjtask.computing.PjTaskComputingEngine;
import com.sunwayworld.basemodule.business.pjtask.dao.LimsPjFolderDao;
import com.sunwayworld.basemodule.business.pjtask.service.LimsPjFolderEquiptService;
import com.sunwayworld.basemodule.business.pjtask.service.LimsPjFolderService;
import com.sunwayworld.basemodule.business.pjtask.service.LimsPjTaskService;
import com.sunwayworld.basemodule.common.auditrecord.service.LimsAuditRecordService;
import com.sunwayworld.basemodule.coredata.pjproduct.bean.LimsPurposeMethodBean;
import com.sunwayworld.basemodule.coredata.pjproduct.service.LimsPurposeMethodService;
import com.sunwayworld.basemodule.coredata.product.bean.LimsProductMainBean;
import com.sunwayworld.basemodule.coredata.product.bean.LimsProductMainPuposeBean;
import com.sunwayworld.basemodule.coredata.product.service.LimsProductMainPuposeService;
import com.sunwayworld.basemodule.coredata.product.service.LimsProductMainService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.database.sql.Order;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.support.PersistableHelper;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsPjFolderServiceImpl implements LimsPjFolderService {

    @Autowired
    private LimsPjFolderDao limsPjFolderDao;

    @Lazy
    @Autowired
    private LimsBatchSampleProductService sampleProductService;

    @Lazy
    @Autowired
    private LimsPjTaskService taskService;

    @Lazy
    @Autowired
    private LimsProductMainPuposeService productMainPuposeService;

    @Lazy
    @Autowired
    private LimsProductMainService productMainService;

    @Lazy
    @Autowired
    private LimsPurposeMethodService purposeMethodService;

    @Lazy
    @Autowired
    private LimsPjFolderEquiptService limsPjFolderEquiptService;

    @Autowired
    @Lazy
    LimsAuditRecordService limsAuditRecordService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsPjFolderDao getDao() {
        return limsPjFolderDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsPjFolderBean limsPjFolder = jsonWrapper.parseUnique(LimsPjFolderBean.class);
        limsPjFolder.setId(ApplicationContextHelper.getNextIdentity());
        getDao().insert(limsPjFolder);
        return limsPjFolder.getId();
    }

    @Transactional
    @Override
    public void insertPjFolders(List<LimsSampleBean> sampleBeans) {
        if (CollectionUtils.isEmpty(sampleBeans)) return;
        List<Long> batchSampleIds = sampleBeans.stream().map(s -> s.getExt$Item("batchSampleId")).map(Long::parseLong).collect(Collectors.toList());
        List<LimsBatchSampleProductBean> batchSampleProductBeans = sampleProductService.getDao()
                .selectListByOneColumnValues(batchSampleIds, "batchSampleId");

        List<Long> productIds = batchSampleProductBeans.stream().map(LimsBatchSampleProductBean::getProductId)
                .distinct().collect(Collectors.toList());
        // 项目检测目的
        List<LimsProductMainBean> limsProductMainBeans = productMainService.selectListByIds(productIds);

        List<LimsProductMainPuposeBean> productBeans = productMainPuposeService.getDao()
                .selectListByOneColumnValues(productIds, "productMainId");

        List<Long> purposeIds = productBeans.stream().map(LimsProductMainPuposeBean::getPurposeId).distinct().collect(Collectors.toList());
        List<LimsPurposeMethodBean> methodBeans = purposeMethodService.selectListByFilter(SearchFilter.instance()
                .match("purposeId", purposeIds).filter(MatchPattern.OR));

        List<LimsPjFolderBean> insertPjFolders = new ArrayList<>();
        List<LimsPjTaskBean> insertPjTasks = new ArrayList<>();
        List<String> folderCodeList = ApplicationContextHelper.getNextSequenceList(getDao().getTable(), "PJ", batchSampleProductBeans.size());
        List<Long> folderIdList = ApplicationContextHelper.getNextIdentityList(batchSampleProductBeans.size());
        int codeIndex = 0;
        int idIndex = 0;
        for (LimsBatchSampleProductBean batchSampleProductBean : batchSampleProductBeans) {
            LimsProductMainBean productMainBean = limsProductMainBeans.stream().filter(p -> p.getId().equals(batchSampleProductBean.getProductId())).findFirst().get();
            List<LimsProductMainPuposeBean> puposeBeans = productBeans.stream().filter(p ->
                    p.getProductMainId().equals(batchSampleProductBean.getProductId())).collect(Collectors.toList());

            LimsPjFolderBean folderBean = new LimsPjFolderBean();
            folderBean.setFolderCode(folderCodeList.get(codeIndex ++));
            folderBean.setId(folderIdList.get(idIndex ++));
            folderBean.setBatchId(batchSampleProductBean.getBatchId());
            folderBean.setBatchCode(batchSampleProductBean.getBatchCode());
            folderBean.setBatchSampleId(batchSampleProductBean.getBatchSampleId());
            folderBean.setSampleId(batchSampleProductBean.getSampleId());
            folderBean.setSampleCode(batchSampleProductBean.getSampleCode());
            folderBean.setProductId(batchSampleProductBean.getProductId());
            folderBean.setProductCode(batchSampleProductBean.getProductCode());
            folderBean.setProductName(batchSampleProductBean.getProductName());
            folderBean.setProfessionalGroup(productMainBean.getProfessionalGroup());
            folderBean.setDeliveryTime(batchSampleProductBean.getPredictDeliveryTime());
//            if (productMainBean.getStandardCycle() != null) {
//                folderBean.setDeliveryTime(LocalDateTime.now().plusDays(Long.parseLong(productMainBean.getStandardCycle())));
//            }
            for (LimsProductMainPuposeBean mainPuposeBean : puposeBeans) {
                LimsPjTaskBean pjTaskBean = new LimsPjTaskBean();
                pjTaskBean.setFolderId(folderBean.getId());
                pjTaskBean.setBatchId(folderBean.getBatchId());
                pjTaskBean.setPurposeId(mainPuposeBean.getPurposeId());
                pjTaskBean.setPurposeCode(mainPuposeBean.getPurposeCode());
                pjTaskBean.setPurposeName(mainPuposeBean.getPurposeName());
                pjTaskBean.setSort(mainPuposeBean.getSorter());
                pjTaskBean.setUnit(mainPuposeBean.getUnit());
                pjTaskBean.setResultType(mainPuposeBean.getResultType());
                pjTaskBean.setRoundingRule(mainPuposeBean.getRoundingRule());
                pjTaskBean.setFormula(mainPuposeBean.getFormula());
                List<LimsPurposeMethodBean> collect = methodBeans.stream().filter(m -> m.getPurposeId().equals(mainPuposeBean.getPurposeId())).collect(Collectors.toList());
                if (collect.size() == 1) {
                    pjTaskBean.setPurposeMethodId(collect.get(0).getId());
                    pjTaskBean.setMethodCode(collect.get(0).getMethodCode());
                    pjTaskBean.setMethodName(collect.get(0).getMethodName());

                    if (!StringUtils.isBlank(collect.get(0).getEquiptIds()) && !collect.get(0).getEquiptIds().contains(",")) {
                        pjTaskBean.setEquipCode(collect.get(0).getEquiptCode());
                        pjTaskBean.setEquipName(collect.get(0).getEquiptName());
                    }
                }
                insertPjTasks.add(pjTaskBean);
            }
            insertPjFolders.add(folderBean);
        }
        getDao().fastInsert(insertPjFolders);
        List<Long> taskIdList = ApplicationContextHelper.getNextIdentityList(insertPjTasks.size());
        AtomicInteger taskIdIndex = new AtomicInteger();
        insertPjTasks.forEach(p -> p.setId(taskIdList.get(taskIdIndex.getAndIncrement())));
        taskService.getDao().fastInsert(insertPjTasks);
    }

    @Override
    @Transactional
    public JSONObject folderSubmit(RestJsonWrapperBean wrapperBean) {
        JSONObject req = new JSONObject();
        req.put("flag", true);
        List<LimsPjFolderBean> folderBeans = wrapperBean.parse(LimsPjFolderBean.class);
        if (folderBeans.isEmpty()) {
            req.put("message", I18nHelper.getMessage("BASEMODULE.PJ_FOLDER_SUBMIT.NO_DATA"));
            return req;
        }
        if (folderBeans.get(0).getId() == null && !StringUtils.isBlank(folderBeans.get(0).getSampleCode())) {
            List<String> sampleCodes = folderBeans.stream().map(LimsPjFolderBean::getSampleCode).filter(s -> !StringUtils.isBlank(s)).distinct().collect(Collectors.toList());
            folderBeans = this.selectListByParam(SearchFilter.instance().match("sampleCode", sampleCodes).filter(MatchPattern.OR).match("status", "draft").filter(MatchPattern.EQ));
            if (folderBeans.isEmpty()) {
                req.put("message", I18nHelper.getMessage("BASEMODULE.PJ_FOLDER_SUBMIT.NO_DATA"));
                return req;
            }
        }
        List<Long> folderIds = folderBeans.stream().map(LimsPjFolderBean::getId).collect(Collectors.toList());
        List<LimsPjTaskBean> taskBeans = taskService.selectListByFilter(SearchFilter.instance().match("folderId", folderIds).filter(MatchPattern.OR));
        if (taskBeans.stream().anyMatch(t -> StringUtils.isBlank(t.getEquipCode()))) {
            StringBuilder builder = new StringBuilder();
            folderBeans.forEach(f -> {
                if (taskBeans.stream().filter(t -> t.getFolderId().equals(f.getId())).anyMatch(t -> StringUtils.isBlank(t.getEquipCode()))) {
                    builder.append(f.getFolderCode()).append(",<br/>");
                }
            });
            builder.append(I18nHelper.getMessage("BASEMODULE.PJ_FOLDER_SUBMIT.NEED_EQIPT"));
            req.put("flag", false);
            req.put("message", builder.toString());
            return req;
        }
        List<LimsPjFolderEquipBean> folderEquipBeans = new ArrayList<>();
        folderBeans.forEach(f -> {
            taskBeans.stream().filter(t -> t.getFolderId().equals(f.getId())).collect(Collectors.groupingBy(LimsPjTaskBean::getEquipCode)).forEach((eptCode, temp) -> {
                LimsPjFolderEquipBean folderEquipBean = new LimsPjFolderEquipBean();
                LimsPjTaskBean first = temp.get(0);
                folderEquipBean.setId(ApplicationContextHelper.getNextIdentity());

                folderEquipBean.setFolderId(f.getId());
                folderEquipBean.setFolderCode(f.getFolderCode());
                folderEquipBean.setProfessionalGroup(f.getProfessionalGroup());

                folderEquipBean.setBatchId(f.getBatchId());
                folderEquipBean.setBatchCode(f.getBatchCode());
                folderEquipBean.setBatchSampleId(f.getBatchSampleId());

                folderEquipBean.setSampleCode(f.getSampleCode());
                folderEquipBean.setSampleId(f.getSampleId());

                folderEquipBean.setProductId(f.getProductId());
                folderEquipBean.setProductCode(f.getProductCode());
                folderEquipBean.setProductName(f.getProductName());

                folderEquipBean.setEquipCode(first.getEquipCode());
                folderEquipBean.setEquipName(first.getEquipName());

                folderEquipBean.setStatus("logged");
                folderEquipBeans.add(folderEquipBean);

                temp.forEach(t -> {
                    t.setFolderEquipId(folderEquipBean.getId());
                    t.setStatus("logged");
                });
            });
        });

        LimsPjFolderBean update = new LimsPjFolderBean();
        update.setStatus("logged");
        getDao().updateByIds(update, folderIds, "status");

        taskService.getDao().fastUpdate(taskBeans, "folderEquipId", "status");

        limsAuditRecordService.insertAuditRecords(folderIds, "T_LIMS_PJ_FOLDER", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.ORDERTASK"), I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), "");

        if (!folderEquipBeans.isEmpty()) {
            limsPjFolderEquiptService.getDao().fastInsert(folderEquipBeans);
            List<Long> folderEptIds = folderEquipBeans.stream().map(LimsPjFolderEquipBean::getId).collect(Collectors.toList());

            PjTaskComputingEngine.getEngine(folderEptIds).compute();
            limsAuditRecordService.insertAuditRecords(folderEptIds, "T_LIMS_PJ_FOLDER_EQUIP", "任务调度", I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), "");
        }
        return req;
    }

    @Override
    @Transactional
    public JSONObject folderStop(RestJsonWrapperBean wrapperBean) {
        JSONObject req = new JSONObject();
        req.put("flag", true);
        List<LimsPjFolderBean> folderBeans = wrapperBean.parse(LimsPjFolderBean.class);
        if (folderBeans.isEmpty()) {
            return req;
        }
        List<Long> folderIds = folderBeans.stream().map(LimsPjFolderBean::getId).collect(Collectors.toList());
        List<LimsPjTaskBean> taskBeans = taskService.selectListByFilter(SearchFilter.instance().match("folderId", folderIds).filter(MatchPattern.OR));
        List<Long> taskIds = taskBeans.stream().map(LimsPjTaskBean::getId).collect(Collectors.toList());
        LimsPjTaskBean taskUpdate = new LimsPjTaskBean();
        taskUpdate.setStatus("stop");
        taskService.getDao().updateByIds(taskUpdate, taskIds, "status");

        LimsPjFolderBean folderUpdate = new LimsPjFolderBean();
        folderUpdate.setStatus("stop");
        getDao().updateByIds(folderUpdate, folderIds, "status");

        limsAuditRecordService.insertAuditRecords(folderIds, "T_LIMS_PJ_FOLDER", I18nHelper.getMessage("LIMS.MODULE.MENUS.TREE.ORDERTASK"), I18nHelper.getMessage("GIKAM.BUTTON.STOP"), "");
        return req;
    }

    @Override
    public List<LimsPjFolderBean> selectListByParam(MapperParameter parameter) {
        return getDao().selectByParam(parameter).stream().map(m -> PersistableHelper.mapToPersistable(m, LimsPjFolderBean.class)).collect(Collectors.toList());
    }

    @Override
    public List<LimsPjFolderBean> selectListByParam(SearchFilter filter) {
        MapperParameter parameter = new MapperParameter();
        parameter.setFilter(filter);
        return selectListByParam(parameter);
    }

    @Override
    public List<LimsPjFolderBean> selectListByParam(SearchFilter filter, Order... orders) {
        MapperParameter parameter = new MapperParameter();
        parameter.setFilter(filter);
        int var5 = orders.length;
        for (int var6 = 0; var6 < var5; ++var6) {
            Order order = orders[var6];
            parameter.setOrderParam(order.getColumn(), order.getDirection());
        }
        return selectListByParam(parameter);
    }
}
